﻿/************************************************************************************
 * xujiajun@yoozoo.com 御剑
 * 简单将圆形所覆盖的矩形范围进行布尔值存储的碰撞数据类
 * 当发生碰撞时IsHit将返回1，否则返回0
 ***********************************************************************************/

using System.Collections.Generic;
using UnityEngine;

namespace WorldMapBase.Collision
{
    /// <summary>
    /// 简单将圆形所覆盖的矩形范围进行布尔值存储的碰撞数据类
    /// 当发生碰撞时IsHit将返回1，否则返回0
    /// </summary>
    public class CircleSimpleBoolCollisionData : CircleCollisionData<bool>
    {

        /// <summary>
        /// 监听碰撞数据改变的接口
        /// </summary>
        public interface IDataChangeListener
        {
            /// <summary>
            /// 当添加碰撞数据时响应
            /// </summary>
            /// <param name="collisionData">碰撞数据</param>
            void OnAddCollision(CircleSimpleBoolCollisionData collisionData);

            /// <summary>
            /// 当移除碰撞数据时响应
            /// </summary>
            /// <param name="collisionData">碰撞数据</param>
            void OnRemoveCollision(CircleSimpleBoolCollisionData collisionData);
            
            bool OnAddCollisionPreCheck(List<Vector3> colInfos);

        }

        private const ushort UPDATE_FRAME = 5;
        private int currentFrame = 0;
        
        private HashSet<IDataChangeListener> m_ListenerSets;

        private List<Vector3> m_collisionInfos;
        
        public CircleSimpleBoolCollisionData(int gridSize) : base(gridSize)
        {
            m_ListenerSets = new HashSet<IDataChangeListener>();
            m_collisionInfos = new List<Vector3>();
        }

        public void OnUpdate()
        {
            currentFrame++;
            if (currentFrame > UPDATE_FRAME)
            {
                UpdateListeners();
                currentFrame = 0;
            }
        }
        
        public void UpdateListeners()
        {
            foreach (var listener in m_ListenerSets)
            {
                if (listener.OnAddCollisionPreCheck(m_collisionInfos))
                {
                    listener.OnAddCollision(this);
                }
            }
            m_collisionInfos.Clear();
        }
        
        /// <summary>
        /// 以指定坐标为中心，半径所覆盖的区域添加指定碰撞
        /// </summary>
        /// <param name="x">横坐标</param>
        /// <param name="y">纵坐标</param>
        /// <param name="r">半径</param>
        public void AddCollision(float x, float y, float r)
        {
            AddCollision(string.Empty, x, y, r);
            m_collisionInfos.Add(new Vector3(x,y,r));
        }


        
        /// <summary>
        /// 以指定坐标为中心，半径所覆盖的区域移除指定碰撞
        /// </summary>
        /// <param name="x">横坐标</param>
        /// <param name="y">纵坐标</param>
        /// <param name="r">半径</param>
        public void RemoveCollision(float x, float y, float r)
        {
            RemoveCollision(string.Empty, x, y, r);
            foreach (var listener in m_ListenerSets)
            {
                listener.OnRemoveCollision(this);
            }
        }

        /// <summary>
        /// 添加监听者
        /// </summary>
        /// <param name="listener">监听者</param>
        public void AddListener(IDataChangeListener listener)
        {
            if (m_ListenerSets.Add(listener))
            {
                listener.OnAddCollision(this);
            }
        }

        /// <summary>
        /// 移除监听者
        /// </summary>
        /// <param name="listener">监听者</param>
        public void RemoveListener(IDataChangeListener listener)
        {
            m_ListenerSets.Remove(listener);
        }

        protected override void OnClear()
        {
            m_ListenerSets.Clear();
        }

        protected override bool OnNewData()
        {
            return false;
        }

        protected override bool OnAddData(string id, bool t)
        {
            return true;
        }

        protected override bool OnRemoveData(string id, bool t)
        {
            return false;
        }

        protected override string OnIsHit(float x, float y, float r, List<bool> list)
        {
            foreach (var b in list)
            {
                if (b) return "success";
            }
            return null;
        }

        protected override void OnAddDataFinish(string id, float x, float y, float r)
        {

        }

        protected override void OnRemoveDataFinish(string id, float x, float y, float r)
        {

        }
    }

}
